package gee

import (
	"fmt"
	"strings"
)

// 代码示例
// 4.1 动态参数匹配
// 路由注册：/p/:lang
// 请求路径：/p/go
// 匹配过程：
// 根节点匹配 p → 进入子节点 :lang（isWild = true）。
// 设置参数 lang = "go"，返回路由 /p/:lang。
// 4.2 星号通配符匹配
// 路由注册：/*static
// 请求路径：/static/css/style.css
// 匹配过程：
// 根节点匹配 *static → 直接返回路由 /*static。
// 捕获剩余路径 css/style.css 作为参数。
// 5. 设计特点
// 动态路由支持：通过 :param 和 *suffix 实现灵活的路径匹配。
// 高效查找：基于前缀树结构，时间复杂度为 O(n)（n 为路径片段数）。
// 多路径支持：星号匹配时遍历所有可能子节点，确保复杂路由的兼容性。

// node 是路由树的节点
// node 结构体表示前缀树中的一个节点，包含以下字段：

// pattern: 完整路由模式（如 /p/:lang），仅在叶子节点设置。
// part: 当前节点对应的路径片段（如 :lang）。
// children: 子节点集合，表示当前节点的所有子路径。
// isWild: 是否为通配符节点（: 或 * 开头）。
type node struct {
	pattern  string  // 待匹配的url，例如 /p/:lang
	part     string  // 当前节点表示的url中的一部分，例如 :lang
	children []*node // 子节点，即子路径，例如 [doc, tutorial, intro]
	isWild   bool    // 是否精确匹配，part 含有 : 或 * 时为true
}

func (n *node) String() string {
	return fmt.Sprintf("node{pattern=%s, part=%s, isWild=%t}", n.pattern, n.part, n.isWild)
}

// 功能：将路由路径拆分为片段并插入树中。
// 流程：
// 拆分路径为 parts（如 /p/:lang → ["p", ":lang"]）。
// 递归插入每个片段，动态参数（:）或星号（*）标记为 isWild。
// 最后一个片段设置完整路由 pattern。
func (n *node) insert(pattern string, parts []string, height int) {
	if len(parts) == height {
		n.pattern = pattern
		return
	}

	part := parts[height]
	child := n.matchChild(part)
	if child == nil {
		// child = &node{part: part, isWild: part[0] == ':' || part[0] == '*'}
		// 修复：使用 part[0] 并增加边界检查
		isWild := false
		if len(part) > 0 {
			isWild = part[0] == ':' || part[0] == '*'
		}
		child = &node{part: part, isWild: isWild}
		n.children = append(n.children, child)
	}
	child.insert(pattern, parts, height+1)

}

// 功能：根据请求路径查找匹配的路由。
// 关键逻辑：
// 星号匹配：若当前节点以 * 开头，直接返回匹配结果。
// 动态参数：遍历所有匹配的子节点（静态路径或通配符），递归匹配后续路径。
func (n *node) search(parts []string, height int) *node {
	if len(parts) == height || strings.HasPrefix(n.part, "*") {
		if n.pattern == "" {
			return nil
		}
		return n
	}

	part := parts[height]
	children := n.matchChildren(part)

	for _, child := range children {
		result := child.search(parts, height+1)
		if result != nil {
			return result
		}
	}

	return nil
}

// 功能：收集所有注册的路由模式（用于调试或路由列表展示）。
// 流程：递归遍历树，将所有包含 pattern 的节点加入列表。
func (n *node) travel(list *([]*node)) {
	if n.pattern != "" {
		*list = append(*list, n)
	}
	for _, child := range n.children {
		child.travel(list)
	}
}

// 功能：返回第一个匹配的子节点（静态路径或通配符）。
// 逻辑：遍历子节点，匹配 part 或 isWild。
func (n *node) matchChild(part string) *node {
	for _, child := range n.children {
		if child.part == part || child.isWild {
			return child
		}
	}
	return nil
}

// 功能：返回所有匹配的子节点（用于星号匹配时的多路径检查）。
// 逻辑：遍历子节点，匹配 part 或 isWild，并加入结果列表。
func (n *node) matchChildren(part string) []*node {
	nodes := make([]*node, 0)
	for _, child := range n.children {
		if child.part == part || child.isWild {
			nodes = append(nodes, child)
		}
	}
	return nodes
}
